package com.getan.boot.common.json;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.getan.boot.common.utils.StringUtils;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 对 DecimalFormatSerializer 进行代理缓存
 *
 * @author Bruce.Gong
 * @since 1.0.0-SNAPSHOT
 */
@SuppressWarnings("rawtypes")
public class CachedFormatSerializer<T> extends StdSerializer<T> implements ContextualSerializer {

    /**
     * 默认序列化类
     */
    private final JsonSerializer delegateSerializer;

    /**
     * 格式化序列化类缓存
     */
    private final ConcurrentHashMap<String, DecimalFormatSerializer<T>> cache = new ConcurrentHashMap<>();

    public CachedFormatSerializer(Class<T> cls, JsonSerializer serializer) {
        super(cls);
        this.delegateSerializer = serializer;
    }

    @Override
    public JsonSerializer<T> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        String pattern = findJsonFormatPattern(prov, property);
        if (StringUtils.isEmpty(pattern)) {
            return this;
        }
        DecimalFormatSerializer<T> cachedSerializer = cache.get(pattern);
        if (cachedSerializer == null) {
            cachedSerializer = new DecimalFormatSerializer<>(handledType(), pattern);
            cache.put(pattern, cachedSerializer);
        }
        return cachedSerializer;
    }

    public String findJsonFormatPattern(SerializerProvider prov, BeanProperty property) {
        JsonFormat.Value annotation = findFormatOverrides(prov, property, handledType());
        return annotation != null ? annotation.getPattern() : null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void serialize(T value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        delegateSerializer.serialize(value, gen, provider);
    }

}